﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Input;

namespace AnotherGoddamnedTextEditor
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            textEditor1.PreviewKeyDownstuff += new System.Windows.Input.KeyEventHandler(textEditor1_PreviewKeyDownstuff);
            textEditor1.TextChanged += new System.Windows.Controls.TextChangedEventHandler(TextEditor1TextChanged);
            wordfilter = new System.Text.RegularExpressions.Regex(@"[A-Za-z0-9]+");
            Initializeform();
            _assistant.Show();
            if (getfilevalid())
                textEditor1.Openfile(Properties.Settings.Default.OpenedFile);
            DesiredWordCountBox.Text = desiredwords.ToString(CultureInfo.InvariantCulture);
            splitContainer3.Panel1.Controls.Add(_assistant);
        }


        private int _words;

        private int desiredwords
        {
            get { return Properties.Settings.Default.DesiredWords; }
            set { Properties.Settings.Default.DesiredWords = value; }
        }

        private double _hrmncmeanlength;
        private double _avgwordlength;


        private void TextEditor1TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
        {
            try
            {
                try
                {
                    desiredwords = int.Parse(DesiredWordCountBox.Text);
                }
                catch (System.ArgumentNullException)
                {
                }
            }
            catch (System.FormatException)
            {
            }
        }

        private System.Text.RegularExpressions.Regex wordfilter;
        
        private bool getfilevalid()
        {
            try
            {
                System.IO.Path.GetFileName(Properties.Settings.Default.OpenedFile);
            }
            catch (Exception)
            {
                Text = "Unititled";
                return false;
            }
            if (System.IO.Path.IsPathRooted(Properties.Settings.Default.OpenedFile))
            {
                Text = "Another goddamned TextEditor:" +
                       System.IO.Path.GetFileNameWithoutExtension(Properties.Settings.Default.OpenedFile);
                return true;

            }
            else
            {
                Text = "Untitled";
                return false;
            }
        }
/*
        private static int SyllableCount2(string word)
        {
            word = word.ToLower().Trim();
            bool lastWasVowel=false;
            var vowels = new[] { 'a', 'e', 'i', 'o', 'u', 'y' };
            int count=0;

            //a string is an IEnumerable<char>; convenient.
            foreach (var c in word)
            {
                if (!lastWasVowel && vowels.Contains(c))
                {
                    count++;
                    lastWasVowel = true;
                }
                else
                    lastWasVowel = false;
            }

            if ((word.EndsWith("e") || (word.EndsWith("es") || word.EndsWith("ed")))
                  && !word.EndsWith("le"))
                count--;

            return count;
        }
*/

        private static int SyllableCount(string word)
        {
            word = word.ToLower().Trim();
            int count = System.Text.RegularExpressions.Regex.Matches(word, "[aeiouy]+").Count;
            if ((word.EndsWith("e") || (word.EndsWith("es") || word.EndsWith("ed"))) && !word.EndsWith("le"))
                count--;
            return count;
        }

        private void textEditor1_PreviewKeyDownstuff(object sender, System.Windows.Input.KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.N:
                    textEditor1.Newfile();
                    Properties.Settings.Default.OpenedFile = "NOT ASSIGNED" + System.IO.Path.GetInvalidFileNameChars();
                    break;
                case Key.S:
                    if (getfilevalid())
                        textEditor1.Savefile(Properties.Settings.Default.OpenedFile);
                    else
                    {
                        TextSaveBox.ShowDialog();
                        Properties.Settings.Default.OpenedFile = TextSaveBox.FileName;
                        textEditor1.Savefile(Properties.Settings.Default.OpenedFile);
                    }
                    break;
                case Key.O:
                    if (getfilevalid())
                        textEditor1.Savefile(Properties.Settings.Default.OpenedFile);
                    openFileDialog1.ShowDialog();
                    Properties.Settings.Default.OpenedFile = openFileDialog1.FileName;
                    textEditor1.Newfile();
                    textEditor1.Openfile(Properties.Settings.Default.OpenedFile);
                    break;
            }
        }


        private void WordCountTimer_Tick(object sender, EventArgs e)
        {
            if (!backgroundWorker1.IsBusy)
                backgroundWorker1.RunWorkerAsync(textEditor1.Text);
        }


        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressBar1.Maximum = desiredwords;
            try
            {
                progressBar1.Value = _words;
            }
            catch (ArgumentOutOfRangeException)
            {
                
            }
            _assistant.wordcount = _words.ToString() + "/" + desiredwords.ToString();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Properties.Settings.Default.Save();
        }

        /// <summary>
        /// Calculate the harmonic mean for however many integers desired
        /// Actually really quite lightweight, considering how annoying it is to calculate this
        /// by hand.
        /// </summary>
        /// <param name="w">the readings to take a measurement of</param>
        /// <returns>The harmonic mean of integer sequence w</returns>
        private static double HarmonicMean(int[] w)
        {
            double t = 0;

            //addition and division so on a 32bit computer 2 operations per double, probably more,
            //but 4*y is my best estimate here
            for (int y = 0; y < w.Length; y++)
                t += 1/(double) w[y];
            //2 cycles
            return w.Length/t;
        }

        #region Threads

        /// <summary>
        /// Count words using Regex, which apparently is slower than looped counting(that doesn't seem to make that
        /// much sense because looped counting is virtually the same thing).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">e holds the text that is wordcounted</param>
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            _words = wordfilter.Matches((string) e.Argument).Count;
        }


        /// <summary>
        /// Counts the number of characters to a word match
        /// Probably a good thing that it is executed in parallel,
        /// would cost too many cycles to be anything but a waste of time otherwise
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WordLengthThread_DoWork(object sender, DoWorkEventArgs e)
        {
            string alltxt = (string) e.Argument;
            int numberwords = wordfilter.Matches(alltxt).Count;
            int[] allwrd = new int[numberwords];
            double wordlength = 0;
            for (int o = 0; o < wordfilter.Matches(alltxt).Count; o++)
            {
                wordlength = wordlength + wordfilter.Matches(alltxt)[o].Length;
                allwrd[o] = wordfilter.Matches(alltxt)[o].Length;
            }
            _avgwordlength = wordlength/(double) numberwords;
            //Need to calculate the number of cycles required to find mean using harmonic mean method, should be pretty efficient
            _hrmncmeanlength = HarmonicMean(allwrd);
        }

        #endregion Threads

        private void WordLengthTimer_Tick(object sender, EventArgs e)
        {
            if (!WordLengthThread.IsBusy)
                WordLengthThread.RunWorkerAsync(textEditor1.Text);
        }

        /// <summary>
        /// Set the average wordlength on the assistant form to the calculated value
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WordLengthThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            _assistant.wordlength = _avgwordlength.ToString(CultureInfo.InvariantCulture) + "\r\n Harmonic Mean:" +
                                    _hrmncmeanlength.ToString(CultureInfo.InvariantCulture);
        }

        private double _avgsyllable;
        private double _avgwordpersentence;

        private void ReadingCheckCalculation_DoWork(object sender, DoWorkEventArgs e)
        {
            var y = (string) e.Argument;
            SplitSentences(y, out _avgsyllable, out _avgwordpersentence);
           
        }

        private void ReadingCheckCalculation_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this._assistant.readingease =
                (206.835 - (1.015*_avgwordpersentence) - (84.6*_avgsyllable)).ToString(CultureInfo.InvariantCulture) +
                "\r\n Average Syllables per word:" + _avgsyllable.ToString(CultureInfo.InvariantCulture);
            
        }


        private void Form1_Activated_1(object sender, EventArgs e)
        {
        }
    }
}